﻿
namespace MyFurion.Application.Controller
{
    /// <summary>
    /// 登录
    /// </summary>
    //[ApiDescriptionSettings(Name = "Login", Order = 1)]
    //[Route("login")]
    public class LoginController:IDynamicApiController
    {
        private readonly UserRepository _userRepository;
        private readonly RoleRepository _roleRepository;
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly CaptchaHelper _captchaHelper;
        private readonly RedisCacheHelper _redisCacheHelper;
        public LoginController(UserRepository userRepository, RoleRepository roleRepository, IHttpContextAccessor httpContextAccessor, CaptchaHelper captchaHelper, RedisCacheHelper redisCacheHelper)
        {
            _userRepository = userRepository;
            _roleRepository = roleRepository;
            _httpContextAccessor = httpContextAccessor;
            _captchaHelper = captchaHelper;
            _redisCacheHelper = redisCacheHelper;
        }
        /// <summary>
        /// 获取验证码
        /// </summary>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet("getCaptcha")]
        public async Task<CaptchaResult> GetCaptcha(EnumCaptchaType captchaType=EnumCaptchaType.CHAR)
        {
            return await _captchaHelper.CreateCaptcha(captchaType);
        }
        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("login")]
        public async Task<string> Login(LoginInput input)
        {
            //验证码校验
            string checkResult = await _captchaHelper.CheckCaptcha(new CaptchaInput(){ CodeToken = input.CaptchaToken, CaptchaData = input.Captcha },CacheType.MEMORY);
            if (!string.IsNullOrWhiteSpace(checkResult))
            {
                throw Oops.Oh(checkResult);
            }
            //登录账号校验
            string md5Pwd= MD5Encryption.Encrypt(input.Password);
            var userInfo = await _userRepository.GetByAccount(input.LoginName,md5Pwd);
            if (userInfo == null)
            {
                throw Oops.Oh(ErrorMsgConst.LoginError);
            }
            if (userInfo.Status == EnumStatus.Disabled)
            {
                throw Oops.Oh(ErrorMsgConst.AccountDisable);
            }
            //token创建
            long orgId = 0;
            string orgName = "";
            string orgPerIds = "";
            int orgAuthority = 0;
            var orgData = userInfo.OrgData;
            if (orgData != null)
            {
                orgId = orgData.Id;
                orgName = orgData.OrgName;
            }
            //机构数据权限获取
            if (!userInfo.IsSuperAdmin)
            {
                var roleInfo = await _roleRepository.GetOrgPer(userInfo.Id,orgId);      
                if (roleInfo != null)
                {
                    orgAuthority = (int)roleInfo.OrgAuthority;
                    orgPerIds = roleInfo.OrgIds.Any() ? Furion.JsonSerialization.JSON.Serialize(roleInfo.OrgIds) : "";
                }
            }
            string accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
            {
                {ClaimConst.ClAIM_USERID, userInfo.Id},
                {ClaimConst.ClAIM_USERNAME, userInfo.UserName??""},
                {ClaimConst.ClAIM_NICKNAME, userInfo.NickName??""},
                {ClaimConst.ClAIM_SUPERADMIN, userInfo.IsSuperAdmin},
                {ClaimConst.ClAIM_ORGID,orgId},
                {ClaimConst.ClAIM_ORGNAME,orgName??""},
                {ClaimConst.ClAIM_ORGPER,orgAuthority},
                {ClaimConst.ClAIM_ORGPERID,orgPerIds??""}
            });
            //设置token 代码等同于 _httpContextAccessor.HttpContext.Response.Headers["access-token"] = accessToken;
            _httpContextAccessor.HttpContext.SigninToSwagger(accessToken);
            //设置refreshtoken
            if (_httpContextAccessor.HttpContext != null)
            {
                var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken);// 生成刷新Token令牌
                _httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken;// 设置刷新Token令牌
            }
            return accessToken;
        }
        /// <summary>
        /// 无验证码登录
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("loginNoCaptcha")]
        public async Task<string> Login(LoginNoCaptchaInput input)
        {
            //登录账号校验
            string md5Pwd = MD5Encryption.Encrypt(input.Password);
            var userInfo = await _userRepository.GetByAccount(input.LoginName, md5Pwd);
            if (userInfo == null)
            {
                throw Oops.Oh(ErrorMsgConst.LoginError);
            }
            if (userInfo.Status == EnumStatus.Disabled)
            {
                throw Oops.Oh(ErrorMsgConst.AccountDisable);
            }
            //token创建
            long orgId = 0;
            string orgName = "";
            string orgPerIds = "";
            int orgAuthority = 0;
            var orgData = userInfo.OrgData;
            if (orgData != null)
            {
                orgId = orgData.Id;
                orgName = orgData.OrgName;
            }
            //机构数据权限获取
            if (!userInfo.IsSuperAdmin)
            {
                var roleInfo = await _roleRepository.GetOrgPer(userInfo.Id, orgId);
                if (roleInfo != null)
                {
                    orgAuthority = (int)roleInfo.OrgAuthority;
                    orgPerIds = roleInfo.OrgIds.Any()? Furion.JsonSerialization.JSON.Serialize(roleInfo.OrgIds):"";
                }
            }
            string accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
            {
                {ClaimConst.ClAIM_USERID, userInfo.Id},
                {ClaimConst.ClAIM_USERNAME, userInfo.UserName??""},
                {ClaimConst.ClAIM_NICKNAME, userInfo.NickName??""},
                {ClaimConst.ClAIM_SUPERADMIN, userInfo.IsSuperAdmin},
                {ClaimConst.ClAIM_ORGID,orgId},
                {ClaimConst.ClAIM_ORGNAME,orgName??""},
                {ClaimConst.ClAIM_ORGPER,orgAuthority},
                {ClaimConst.ClAIM_ORGPERID,orgPerIds??""}
            });
            //设置token 代码等同于 _httpContextAccessor.HttpContext.Response.Headers["access-token"] = accessToken;
            _httpContextAccessor.HttpContext.SigninToSwagger(accessToken);
            //设置refreshtoken
            if (_httpContextAccessor.HttpContext != null)
            {
                var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken);// 生成刷新Token令牌
                _httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken;// 设置刷新Token令牌
            }
            return accessToken;
        }
        /// <summary>
        /// 退出登录
        /// </summary>
        /// <returns></returns>
        //[AllowAnonymous]
        [HttpPost("logOut")]
        public async Task LogOut()
        {
            string token = "";//token
            string refreshToken = "";//刷新token
            if (App.HttpContext.Request.Headers.ContainsKey("Authorization"))
            {
                token = App.HttpContext.Request.Headers["Authorization"];
            }
            if (App.HttpContext.Request.Headers.ContainsKey("X-Authorization"))
            {
                refreshToken = App.HttpContext.Request.Headers["X-Authorization"];
            }
            await Task.Run(() => 
            {
                if (!string.IsNullOrWhiteSpace(token))
                {
                    _redisCacheHelper.SetCacheMin(token, "黑名单Token", 1440);//token放入黑名单
                }
                if (!string.IsNullOrWhiteSpace(refreshToken))
                {
                    _redisCacheHelper.SetCacheMin(refreshToken, "黑名单RefreshToken", 43200);//refreshtoken放入黑名单
                }
                //移除操作权限缓存
                _redisCacheHelper.DelRedisCache(CurrentUserInfo.UserId+CommonConst.ActionPer_Flag);
                //设置token无效 代码等同于 _httpContext.Response.Headers["access-token"] = "invalid_token";
                _httpContextAccessor.HttpContext.SignoutToSwagger();
            });
        }
        /// <summary>
        /// 获取登录用户信息
        /// </summary>
        /// <returns></returns>
        [HttpGet("userInfo")]
        public async Task<LoginUserInfo> GetUserInfo()
        {
            MenuRepository menuRepository = App.GetService<MenuRepository>();
            var userInfo = await _userRepository.GetDetail(CurrentUserInfo.UserId);//获取用户信息
            var configInfo = await App.GetService<ConfigRepository>().GetFirstAsync(it => it.ConfigCode == "DefaultPwd");//获取初始化密码
            string defaultPwd = configInfo?.ConfigValue;
            string pwdMd5 = MD5Encryption.Encrypt(defaultPwd);
            //获取菜单权限
            List<PermissionInfo> menuPers = await menuRepository.GetMenuPer();
            //获取菜单操作标识（menuCode）
            List<string> menuCodes = await menuRepository.GetActionPer();
            //将菜单标识放入redis缓存
            if (menuCodes.Any())
            {
                _redisCacheHelper.SetRedisCache(userInfo.Id + CommonConst.ActionPer_Flag,Newtonsoft.Json.JsonConvert.SerializeObject(menuCodes));
            }
            LoginUserInfo loginUserInfo = new LoginUserInfo();
            loginUserInfo.UserName = userInfo.UserName;
            loginUserInfo.NickName = userInfo.NickName;
            loginUserInfo.IsSuperAdmin = userInfo.IsSuperAdmin;
            loginUserInfo.OrgName = userInfo.OrgData?.OrgName;
            loginUserInfo.IsDefaultPwd = pwdMd5 == userInfo.LoginPwd;
            loginUserInfo.MenuPer= menuPers;
            return loginUserInfo;
        }
    }
}
